<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
<script>

// async/await用于解决异步编程
// async是一个修饰符，用于修饰函数
// await命令是等待的意思，等待后面表达式的结果
// 注意：await命令必须在async函数中使用

// console.log( 1 );
// async function test(){
//     console.log( 2 );
//     let res = await 1+2;
//     // 执行完上面的代码后，跳出test函数执行流，执行函数外部的同步程序，然后再回到test函数继续执行后面的程序
//     console.log( res );// 3
// }
// test();
// console.log( 4 );
// 1 2 4 3


// console.log( 1 );
// async function show(){
//     console.log( 2 );
//     // await只能等待到后面Promise对象成功的结果（await是一种阻塞模式）
//     let res = await new Promise((resolve,reject)=>{
//         console.log( 3 );
//         setTimeout(()=>{
//             console.log( '异步程序' );
//             resolve(4);
//         },20);
//     });
//     // 执行完上面的代码后，跳出show函数执行流，执行函数外部的同步程序，然后再回到show函数继续执行后面的程序
//     console.log( res );// 4
// }
// show();
// console.log( 5 );
// 1 2 3 5 4


// 事件循环机制 Event Loop
// 浏览器渲染进程中的主要线程:
// 1.GUI渲染线程，主要负责渲染页面
// 2.JS引擎线程，主要负责解析执行JS脚本
    // GUI渲染线程和JS引擎线程是互斥的关系（JS脚本会阻塞页面渲染）
// 3.事件触发线程，主要负责事件管理和控制
    // 事件触发线程管理着一个事件队列/任务队列
    // 事件队列中的回调函数等待JS引擎空闲时来处理
// 4.计时器线程，主要负责给某个函数计时
// 5.异步http请求线程，主要负责等待异步请求响应状态改变

// 1.要执行一段JS脚本，js引擎线程先解析这段代码，然后将同步程序按照执行顺序加入执行栈
// 2.当js引擎遇到异步事件时，并不会等待异步事件的结果，交给其他线程处理，继续执行后面的程序
// 3.当异步事件有结果时，对应的回调函数被加入事件队列，等待js引擎空闲时来处理
// 4.当js引擎执行回调函数时，回调函数中又可能有同步和异步程序，重复上述123步骤
// 5.上述描述的程序执行过程 即 '事件循环 Event Loop'

// 不同的异步任务也有区别：
// 宏任务：计时器、ajax请求
// 微任务：Promise

async function async1(){
    console.log( 1 );
    await async2();
    console.log( 2 );
}
async function async2(){
    console.log( 3 );
}
console.log( 4 );
setTimeout(()=>{// f1
    console.log( 5 );
},0);
async1();
new Promise((resolve,reject)=>{// f2
    console.log( 6 );
    resolve();
})
.then(()=>{// f3
    console.log( 7 );
});
console.log( 8 );
// 4 1 3 6 8 2 7 5

// 模拟上述代码执行过程：
// 微队列：[f3]
// 宏队列：[f1]
// Call Stack执行栈：
// console.log( 4 );
// setTimeout(); 给f1计时0毫秒，f1被加入宏队列
// async1();
    // console.log( 1 );
    // await async2();
    // async2();
        // console.log( 3 );
        // 返回一个成功状态的Promise对象，结果为undefined
    // 跳出当前函数执行流，执行async1函数外部的同步程序
// new Promise()
    // f2();
        // console.log( 6 );
        // resolve(); -> Promise对象为成功状态
// .then() -> f3符合执行条件，f3加入微队列
// console.log( 8 );
// 此时，js引擎线程空闲了，回调async1函数内部继续执行await后面的程序
// console.log( 2 );
// 此时，js引擎线程空闲了，优先处理微队列，再处理宏队列
// f3();
    // console.log( 7 );
// 此时，js引擎线程空闲了，优先处理微队列，再处理宏队列
// f1();
    // console.log( 5 );

</script>
</body>
</html>